#ifndef AZABSTRACTDATASOURCE_H
#define AZABSTRACTDATASOURCE_H



#include <QVector>

#include "Az.h"
#include "AzField.h"
#include "AzRecord.h"

class AzRootRecord;

class AZLIB_EXPORT AzDataSourceException : public AzException {
public:
    enum Error {
        NoError                             = 0x0,
        NotOpenError                        = 0x1,
        AllreadyOpenError                   = 0x2,
        ConnectionError                     = 0x3,
        OpenError                           = 0x4,
        ReadOnlyError                       = 0x5,
        WriteOnlyError                      = 0x6,
        NoMetadataFoundError                = 0x7,
        WrongDataFormatError                = 0x8,
        InvalidFieldTypeError               = 0x9,
        UnsupportedFieldTypeError           = 0x10,
        UnknownError                        = 0x255
    };

    AzDataSourceException(Error = NoError,int = 0,const QString& = QString());
    AzDataSourceException(const AzDataSourceException&);

    Error error() const                 { return mErrorCode;            }
    int nativeErrorCode() const         { return mNativeErrorCode;      }
    QString nativeErrorMessage() const   { return mNativeErrorMessage;   }

    static QString codeToMessage(Error);
    AzDataSourceException& operator     = (const AzDataSourceException&);
protected:
    QString mNativeErrorMessage;
private:
    void copy(const AzDataSourceException&);
    Error mErrorCode;
    int mNativeErrorCode;

};

typedef AzDataSourceException AzDataSourceError;
typedef QVector<QPair <AzDataSourceError,AzRecord*> > AzDionisWriteError;

class AzAbstractDataSource: public QObject {
Q_OBJECT
public:

    explicit AzAbstractDataSource(Az::DataPacketFlags,QObject*);
    virtual ~AzAbstractDataSource();
    inline Az::DataSourcePropertyFlags flags() const    { return mFlags; }

    virtual bool isConnectReadOnly() const = 0;
    virtual void open(bool = false);
    virtual void close();
    inline bool readOnly() const                        { return mReadOnly; }
    bool isOpen() const                                 { return mFields.size() !=0 ; }

    QString name() const                                { return mName; }
    void setName(const QString& src)                    { mName = src;}

    inline AzFieldList &fields()                        { return mFields; }
    inline void setFields(const AzFieldList& src)       { mFields = src; }

    inline Az::DataPacketFlags dataPacketFlags() const  { return mDataPacketFlags; }

    int writeData(const AzRecord* savedData,AzDionisWriteError *error = 0, int maxErrors = -1);
    int readData(AzRecord* records, const AzRecord* parent,int packetSize);

    void setDataPacketFlags(Az::DataPacketFlags flags)  { mDataPacketFlags = flags; }

signals:

    void beforeWriteChildRecords(const AzRecord*);
    void afterWriteChildRecords(const AzRecord*);

    void beforeWriteRecord(const AzRecord*);
    void afterWriteRecord(const AzRecord*);

protected:
    void setReadOnly(bool readOnly)                     { mReadOnly = readOnly; }


    virtual void internalOpen() =  0;
    virtual void internalClose() = 0;
    virtual void estabsilshConnection() = 0;

    virtual AzFieldList readMetadata() = 0;
    virtual void writeMetadata(const AzFieldList&) {}

    virtual void writeRecord(const AzRecord*) = 0;
    virtual int readRecords(AzRecord*, const AzRecord*,int) = 0;



    virtual inline void doBeforeWrite()  {}
    virtual inline void doAfterWrite() {}

    virtual inline void doBeforeRead() {}
    virtual inline void doAfterRead() {}


    virtual inline void doBeforeWriteChildRecords(const AzRecord*) {}
    virtual inline void doAfterWriteChildRecords(const AzRecord*) {}


private:
    int writeRecords(const AzRecord*);

    const Az::DataSourcePropertyFlags mFlags;
    Az::DataPacketFlags mDataPacketFlags;
    AzFieldList mFields;
    bool mReadOnly;
    QString mName;
};


#endif // AZABSTRACTDATASOURCE_H
